forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1import * as v from 'valibot'
2import { PackageRouteParamsSchema } from '#shared/schemas/package'
3import { CACHE_MAX_AGE_ONE_HOUR, ERROR_CALC_INSTALL_SIZE_FAILED } from '#shared/utils/constants'
4
5/**
6 * GET /api/registry/install-size/:name or /api/registry/install-size/:name/v/:version
7 *
8 * Calculate total install size for a package including all dependencies.
9 * Handles platform-specific optional dependencies by counting only one representative per group.
10 */
11export default defineCachedEventHandler(
12 async event => {
13 // Parse package name and optional version from path segments
14 // Supports: /install-size/lodash, /install-size/lodash/v/4.17.21, /install-size/@scope/name, /install-size/@scope/name/v/1.0.0
15 const pkgParamSegments = getRouterParam(event, 'pkg')?.split('/') ?? []
16
17 const { rawPackageName, rawVersion } = parsePackageParams(pkgParamSegments)
18
19 try {
20 const { packageName, version: requestedVersion } = v.parse(PackageRouteParamsSchema, {
21 packageName: rawPackageName,
22 version: rawVersion,
23 })
24
25 // If no version specified, resolve to latest using fast-npm-meta (lightweight)
26 let version: string | undefined = requestedVersion
27 if (!version) {
28 const latestVersion = await fetchLatestVersionWithFallback(packageName)
29 if (!latestVersion) {
30 throw createError({
31 statusCode: 404,
32 message: 'No latest version found',
33 })
34 }
35 version = latestVersion
36 }
37
38 return await calculateInstallSize(packageName, version)
39 } catch (error: unknown) {
40 handleApiError(error, {
41 statusCode: 502,
42 message: ERROR_CALC_INSTALL_SIZE_FAILED,
43 })
44 }
45 },
46 {
47 maxAge: CACHE_MAX_AGE_ONE_HOUR,
48 swr: true,
49 getKey: event => {
50 const pkg = getRouterParam(event, 'pkg') ?? ''
51 return `install-size:v1:${pkg.replace(/\/+$/, '').trim()}`
52 },
53 },
54)